package com.chen.project.white_jotter.service.admin;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chen.project.white_jotter.mapper.JotterArticleMapper;
import com.chen.project.white_jotter.pojo.JotterArticle;
import com.chen.project.white_jotter.utils.RedisUtil;
import com.chen.project.white_jotter.utils.SecurityUtil;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class JotterArticleService {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private JotterArticleMapper jotterArticleMapper;

    @Resource
    private ElasticsearchRestTemplate esTemplate;

    // 获取一篇文章的md
    public JotterArticle getJotterMdById(Integer id) {

        JotterArticle jotterArticle = null;

        if (redisUtil.get("md_" + id) != null) {
            System.out.println("redis");
            jotterArticle = (JotterArticle) redisUtil.get("md_" + id);
        } else {
            System.out.println("mysql");
            jotterArticle = jotterArticleMapper.selectById(id);
            redisUtil.set("md_" + id, jotterArticle);
            redisUtil.expire("md_" + id, 20L, TimeUnit.MINUTES);
        }

        System.out.println("查到的文章说" + jotterArticle);

        return jotterArticle;
    }

    // 获取一页文章
    public Map<String, Object> getPageArticle(Integer pageNum, Integer pageSize, String query) {

        System.out.println(query);

        HashMap<String, Object> map = new HashMap<>();
        Page<JotterArticle> page = new Page<>(pageNum, pageSize);

        List<JotterArticle> articleList = null;
        Integer count = 0;

        // 获取当前用户的权限（角色）、用户名
        String role = SecurityUtil.getCurrentUserGrantedAuthority().get(0).getAuthority();
        String currentUsername = SecurityUtil.getCurrentUsername();
        System.out.println("当前登录用户的角色为" + role);

        System.out.println("".equals(null));

        // 判断用户权限（角色），如果是管理员，可以获取所有文章，这里不区分前后台
        if ("ROLE_admin".equals(role)) {
            // 有query条件，说明是后台查询
            if (query != null && !"".equals(query)) {
                QueryWrapper<JotterArticle> queryWrapper = new QueryWrapper<>();
                queryWrapper.like("article_title", query);
                articleList = jotterArticleMapper.selectPage(page, queryWrapper).getRecords();
                count = jotterArticleMapper.selectCount(queryWrapper);
                map.put("articleList", articleList);
                map.put("count", count);
                return map;
            }
            // 缓存中有文章
            if (redisUtil.get("article_list_page_" + pageNum + "_" + pageSize) != null) {
                map = (HashMap<String, Object>) redisUtil.get("article_list_page_" + pageNum + "_" + pageSize);
            }
            // 查询数据库
            else {

                articleList = jotterArticleMapper.selectPage(page, null).getRecords();
                count = jotterArticleMapper.selectCount(null);

                map.put("articleList", articleList);
                map.put("count", count);

                redisUtil.set("article_list_page_" + pageNum + "_" + pageSize, map);
                redisUtil.expire("article_list_page_" + pageNum + "_" + pageSize, 20L, TimeUnit.MINUTES);
            }
        }
        // 普通用户前台可以获取所有文章，后台只能获取自己的文章
        else if ("ROLE_normal".equals(role)) {
            // 普通用户的前台文章
            if (pageSize == 4) {
                if (redisUtil.get("article_list_page_" + pageNum + "_" + pageSize) != null) {
                    map = (HashMap<String, Object>) redisUtil.get("article_list_page_" + pageNum + "_" + pageSize);
                } else {

                    articleList = jotterArticleMapper.selectPage(page, null).getRecords();
                    count = jotterArticleMapper.selectCount(null);

                    map.put("articleList", articleList);
                    map.put("count", count);

                    redisUtil.set("article_list_page_" + pageNum + "_" + pageSize, map);
                    redisUtil.expire("article_list_page_" + pageNum + "_" + pageSize, 20L, TimeUnit.MINUTES);
                }
            }
            // 普通用户的后台文章
            else if (pageSize == 10) {
                // 有query条件，说明是后台查询
                if (query != null && !"".equals(query)) {
                    QueryWrapper<JotterArticle> queryWrapper = new QueryWrapper<>();
                    queryWrapper.like("article_title", query);
                    articleList = jotterArticleMapper.selectPage(page, queryWrapper).getRecords();
                    count = jotterArticleMapper.selectCount(queryWrapper);
                    map.put("articleList", articleList);
                    map.put("count", count);
                    return map;
                }
                if (redisUtil.get("article_list_page_normal_" + currentUsername + "_" + pageNum) != null) {
                    map = (HashMap<String, Object>) redisUtil.get("article_list_page_normal_" + currentUsername + "_" + pageNum);
                } else {
                    QueryWrapper<JotterArticle> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("article_author", currentUsername);
                    articleList = jotterArticleMapper.selectPage(page, queryWrapper).getRecords();
                    count = jotterArticleMapper.selectCount(queryWrapper);

                    map.put("articleList", articleList);
                    map.put("count", count);

                    redisUtil.set("article_list_page_normal_" + currentUsername + "_" + pageNum, map);
                    redisUtil.expire("article_list_page_normal_" + currentUsername + "_" + pageNum, 20L, TimeUnit.MINUTES);
                }
            }
        }

        return map;
    }

    // 更新文章
    public int updateArticle(JotterArticle jotterArticle) {

        int i = jotterArticleMapper.updateById(jotterArticle);
        Set<String> keys = redisUtil.keys("*");
        redisUtil.delete(keys);
        return i;
    }

    // 添加文章
    public int addJotterArticle(JotterArticle jotterArticle) {

        int i = jotterArticleMapper.insert(jotterArticle);

        Set<String> keys = redisUtil.keys("*");
        redisUtil.delete(keys);

        return i;
    }

    // 删除文章
    public int deleteArticleById(Integer id) {

        int i = jotterArticleMapper.deleteById(id);
        Set<String> keys = redisUtil.keys("*");
        redisUtil.delete(keys);
        return i;
    }

    public Map<String, Object> search(String keyword) {

        Map<String, Object> map = new HashMap<>();

        System.out.println("关键词是：" + keyword);
        ArrayList<JotterArticle> list = new ArrayList<>();

        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("articleAbstract", keyword))
                .withHighlightBuilder(new HighlightBuilder().field("articleAbstract").preTags("<span style='color:red;'>").postTags("</span>"))
                .build();
        SearchHits<JotterArticle> searchHits = esTemplate.search(query, JotterArticle.class);
        List<SearchHit<JotterArticle>> hitList = searchHits.getSearchHits();

        if(hitList.size() == 0){
            map.put("articleList", list);
            map.put("count", hitList.size());
            return map;
        }

        for (SearchHit<JotterArticle> hit : hitList) {

            List<String> highlightList = hit.getHighlightField("articleAbstract");
            JotterArticle article = hit.getContent();
            article.setArticleAbstract(highlightList.get(0));
            list.add(article);
        }

        map.put("articleList", list);
        map.put("count", hitList.size());
        return map;
    }
}
